package com.greatwqs.wmall.product.provider.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageInterceptor;
import com.greatwqs.wmall.common.provider.utils.DataSourceUtil;

import lombok.extern.slf4j.Slf4j;

import org.apache.ibatis.session.LocalCacheScope;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.seata.rm.datasource.DataSourceProxy;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

import java.util.Properties;

/***
 *
 * @author wang-qingsong
 */
@Slf4j
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan(basePackages = "com.greatwqs.wmall.product.provider.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
public class MyBatisConfig {

    private static final String MAPPER_LOCATION = "classpath:mapper/*.xml";
    private static final String PO_PACKAGE = "com.greatwqs.wmall.product.provider.model.po";

    @Bean("druidDataSource")
    public DruidDataSource druidDataSource(
            @Value("${spring.datasource.url}") String url,
            @Value("${spring.datasource.username}") String username,
            @Value("${spring.datasource.password}") String password,
            @Value("${spring.datasource.driver-class-name}") String driverClassName,
            @Value("${spring.datasource.minimum-idle:2}") int conInitialSize,
            @Value("${spring.datasource.maximum-pool-size:5}") int conMaxActive) {
        log.warn("dataSource conInitialSize: " + conInitialSize + ", conMaxActive: " + conMaxActive);
        return DataSourceUtil.getDruid(url, username, password, driverClassName, conInitialSize, conMaxActive);
    }

    @Primary
    @Bean("dataSource")
    public DataSource dataSource(@Qualifier("druidDataSource") DruidDataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }

    @Primary
    @Bean("transactionManager")
    public DataSourceTransactionManager transactionManager(
            @Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Primary
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(
            @Qualifier("dataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setLocalCacheScope(LocalCacheScope.STATEMENT);
        sessionFactory.setConfiguration(configuration);
        sessionFactory.setTypeAliasesPackage(PO_PACKAGE);
        sessionFactory.setPlugins(this.pageHelperPlugin());
        return sessionFactory.getObject();
    }

    /**
     * page helper config
     */
    private PageInterceptor pageHelperPlugin() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "mysql");
        //properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("params", "count=countSql;");
        //properties.setProperty("offsetAsPageNum", "true");
        properties.setProperty("autoRuntimeDialect", "true");
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
}
